package com.bookmngsys.service.impl;

import com.bookmngsys.dao.*;
import com.bookmngsys.entity.*;
import com.bookmngsys.service.ReservationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @author han
 */
@Service
public class ReservationServiceImpl implements ReservationService {

    @Autowired
    ReservationDao reservationDao;

    @Autowired
    ReaderDao readerDao;

    @Autowired
    BookDao bookDao;

    @Autowired
    BookInfoDao bookInfoDao;

    @Autowired
    BorrowHistoryDao borrowHistoryDto;
    @Autowired
    ReservationHistoryDao reservationHistoryDao;
    @Autowired
    FineHistoryDao fineHistoryDao;

    @Override
    public void  test(){
        Reservation r = reservationDao.getById(1);
        System.out.println(r.getReaderId());
    }

    @Override
    public List<Reservation> getReservations() {
        return reservationDao.findAll();
    }

    @Override
    public List<Reservation> getReservationsByReaderId(int readerId) {
        List<BookInfo> bookInfos = bookInfoDao.findAllReservationByReaderId(readerId);
        ArrayList<Reservation> reservations = new ArrayList<>();
        if(bookInfos == null || bookInfos.size() == 0){
            return reservations;
        }
        for(BookInfo bookInfo1:bookInfos){
            Reservation reservation = new Reservation();
            reservation.setIsbn(bookInfo1.getIsbn());
            reservation.setId(bookInfo1.getBookId());
            reservation.setReaderId(readerId);
            if(bookInfo1.getReserveDate() == null || bookInfo1.getReserveReaderId() == null){
                reservation.setReservationDate(new Date(System.currentTimeMillis() - 15000 * 1000));
                reservation.setStatus(0);
            }else if(bookInfo1.getReserveDate() + 14400 * 1000 >= System.currentTimeMillis()){
                reservation.setStatus(1);
                reservation.setReservationDate(new Date(bookInfo1.getReserveDate()));
            }else{
                reservation.setStatus(0);
                reservation.setReservationDate(new Date(bookInfo1.getReserveDate()));
            }
            reservations.add(reservation);
        }
        return reservations;
    }

    @Override
    public Reservation getReservation(int id) {
        Reservation reservation = reservationDao.getById(id);
        return reservation;
    }

    int getNumOfOverdue(int readerId){
        ArrayList<BookInfo> bookInfos = bookInfoDao.getBorrowBookByReaderId(readerId);
        int overdue = 0;
        for(BookInfo bookInfo:bookInfos){
            if(System.currentTimeMillis() > bookInfo.getReturnDate()){
                overdue++;
            }
        }
        return overdue;
    }

    @Override
    public void reserve(String isbn, int readerId) throws Exception {
        if(bookDao.getById(isbn) == null){
            throw new Exception("无此书");
        }else if(getNumOfOverdue(readerId) != 0){
            throw new Exception("you have book overdue, please pay fine");
        }else if(bookInfoDao.getReservationNumByReaderId(readerId, System.currentTimeMillis()) == 3){
            throw new Exception("exceed reservation time");
        }else if(bookInfoDao.getBorrowNumByReaderId(readerId) == 5){
            throw new Exception("exceed borrow time");
        }else{
            BookInfo bookInfo1 = bookInfoDao.findBorrowBookByIsbnAndReaderId(isbn, readerId);
            BookInfo bookInfo2 = bookInfoDao.findReservationByIsbnAndReaderId(isbn, readerId, System.currentTimeMillis());
            if(bookInfo1 != null){
                throw new Exception("have borrowed this isbn");
            }else if(bookInfo2 != null){
                throw new Exception("have reserved this isbn");
            }
            ArrayList<BookInfo> bookInfos = bookInfoDao.findCanReservationByIsbn(isbn, System.currentTimeMillis());
            if(bookInfos == null || bookInfos.size() == 0){
                throw new Exception("book is not enough");
            }
            for(BookInfo x: bookInfos){
                if (x.getLost() != 0 && x.getDamage() != 0) {
                    bookInfo1 = x;
                    break;
                }
            }
            if(bookInfo1 == null){
                throw new Exception("book is enough but all books are damaged or lost");
            }
            bookInfo1 = bookInfos.get(0);
            bookInfo1.setReserveDate(System.currentTimeMillis());
            bookInfo1.setReserveReaderId(readerId);
            bookInfoDao.save(bookInfo1);

            {//向reservation_history中插入预约历史信息
                ReservationHistory a = new ReservationHistory();
                a.setId((new Random(System.currentTimeMillis())).nextInt(Integer.MAX_VALUE));
                a.setReserveDate(bookInfo1.getReserveDate());
                a.setBookId(bookInfo1.getBookId());
                a.setIsbn(bookInfo1.getIsbn());
                a.setReaderId(bookInfo1.getReserveReaderId());
                a.setIsUsed(false);
                a.setIsCancelled(false);
                reservationHistoryDao.save(a);
            }

        }
    }

    @Override
    public void cancelReserve(int bookId) throws Exception{
        BookInfo bookInfo = bookInfoDao.findReservationByBookId(bookId, System.currentTimeMillis());
        if(bookInfo == null) {
            throw new Exception("cannot find reservation");
        }else{
            {
                //同步更改reservation_history表
                ReservationHistory a = reservationHistoryDao.findValidReservation(bookInfo.getReserveReaderId(),
                        bookInfo.getIsbn(),
                        bookInfo.getBookId(),
                        bookInfo.getReserveDate());
                if(a != null){
                    a.setIsCancelled(true);
                    reservationHistoryDao.save(a);
                }
            }
            bookInfo.setBorrowDate(null);
            bookInfo.setReturnDate(null);
            bookInfo.setBorrowReaderId(null);
            bookInfo.setReserveDate(null);
            bookInfo.setReserveReaderId(null);
            bookInfo.setFine(0.0f);
            bookInfoDao.save(bookInfo);
        }

    }


}
